/**
 * copyright (c) by handpay 2013
 */
package com.handpay.framework.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;

import com.handpay.framework.SecureManager;
import com.handpay.zztong.hp.ZZTApplication;
import com.handpay.zztong.hp.bean.Account;
import com.handpay.zztong.hp.bean.AppealInfo;
import com.handpay.zztong.hp.bean.Bill;
import com.handpay.zztong.hp.bean.WithdrawRecordsBill;
import com.handpay.zztong.hp.config.ZZTConfig;
import com.handpay.zztong.hp.config.ZZTConstant;
import com.handpay.zztong.hp.log.HPLog;
import com.handpay.zztong.hp.webpay.model.AccountTransfer;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import java.util.zip.CRC32;

import se.krka.kahlua.vm.LuaTable;

/**
 * @author：Klaus Liu E-mail: lpluck08@gmail.com
 * @date：2013-3-20 下午03:59:51
 */
public class CommonUtils {

    /**
     * 将float类型的人民币数字格式化为带￥且保留两位小数的字符串
     *
     * @param money
     * @return
     */
    public static String formatMoney(double money) {
        DecimalFormat df = new DecimalFormat("0.00");
        return "¥" + df.format(money);
    }

    /***
     * @param amount 金额
     * @return 返回格式化之后的金额
     */
    public static String getFromatMoney(Double amount) {
        double amV = (amount / 100.00);
        DecimalFormat decimalFormat = new DecimalFormat(".00");// 构造方法的字符格式这里如果小数不足2位,会以0补足.
        String p = decimalFormat.format(amV);
        //这里暂时这么写当收款金额为0.01   p经过转换后变成 .01
        if (p != null && p.contains(".") && p.substring(0, 1).equals(".")) {
            p = "0" + p;
        }
        return p;
    }

    /**
     * 将float类型的人民币数字格式化为保留两位小数的字符串
     *
     * @param money
     * @return
     */
    public static String formatMoneyDouble(double money) {
        DecimalFormat df = new DecimalFormat("0.00");
        return df.format(money);
    }

    public static String formatMoneyToPos(Double money, int totalLen) {
        HPLog.e("formatMoneyToPos", "money:" + money + "amountLen:" + totalLen);
        String moneyStr = money.intValue() + "";
        //测试转账的时候金额0.01报错
        if (moneyStr.length() == 1) {
            moneyStr = "0".concat(moneyStr);
        }
        return "0000000000".substring(0, totalLen - moneyStr.length()) + moneyStr;
    }

    /**
     * 格式化金额为12位的,主要是为发往银联的交易 送进来的金额是元的,转成12位之后就是分了 比如商城传来的是50.0元 那么传给银联就是
     * 000000005000
     *
     * @param transAmount
     * @return
     * @author fyang
     */
    public static String formatMoenyToUnionpay(String transAmount) {
        BigDecimal money = new BigDecimal(String.valueOf(transAmount));
        money.multiply(new BigDecimal(100)).intValue();
        String result = "0000000000000" + money.multiply(new BigDecimal(100)).intValue();
        result = result.substring(result.length() - 12);
        return result;
    }

    /**
     * 把金额以元为单位,转化为以分为单位 比如商城传过来的是50.0元 那么就是对应 5000分
     *
     * @param transAmount
     * @return
     * @author fyang
     */
    public static String formatMoenyToCurrency(String transAmount) {
        BigDecimal money = new BigDecimal(String.valueOf(transAmount));
        money.multiply(new BigDecimal(100)).intValue();
        String result = money.multiply(new BigDecimal(100)).intValue() + "";
        return result;
    }

    public static String getCRC(CRC32 crc, byte[] bytes) {
        if (null == crc) {
            return "";
        }
        crc.reset();
        crc.update(bytes);
        return String.valueOf(crc.getValue());
    }

    /**
     * 将账单lua数据转化为Account对象,需要放到Account.java里?
     *
     * @param data
     * @return
     */
    public static Account generateAccount(LuaTable data, String cardUser) {
        Account a = new Account();
        a.setBankID((String) data.rawget("bankID"));
        a.setCardID((String) data.rawget("cardID"));
        a.setCardNo((String) data.rawget("cardNo"));
        // 银行卡别名，没有作用。用cardUser来代替
        if (!TextUtils.isEmpty(cardUser)) {
            a.setCardName(cardUser);
        } else {
            a.setCardName((String) data.rawget("cardName"));
        }
        String ac = (String) data.rawget("accountNumber");
        if (!TextUtils.isEmpty(ac)) {
            ac = SecureManager.getInstance().des(ac, 0, null);
        } else {
            HPLog.e("CommonUtils", "accountNumber empty!");
        }
        a.setCardPlainNo(ac);
        return a;
    }

    /**
     * 将账单lua数据转化为Bill对象,需要放到Bill.java里?
     *
     * @param data
     * @return
     */
    public static AppealInfo generateAppeal(LuaTable data) {
        AppealInfo appealInfo = new AppealInfo();
        appealInfo.setTransSN((String) data.rawget("transSN"));
        appealInfo.setAppealId((String) data.rawget("appealId"));
        appealInfo.setAppealContent((String) data.rawget("appealContent"));
        appealInfo.setAppealTime((String) data.rawget("appealTime"));
        appealInfo.setAppealType((Integer.valueOf((String) data.rawget("appealType")).intValue()));
        appealInfo.setAppealStatus((Integer.valueOf((String) data.rawget("appealStatus")).intValue()));
        appealInfo.setMerchantCode((String) data.rawget("merchantCode"));
        appealInfo.setTransTime((String) data.rawget("transTime"));
        appealInfo.setReplyContent((String) data.rawget("replyContent"));
        appealInfo.setReplyTime((String) data.rawget("replyTime"));
        appealInfo.setOutputCardNo((String) data.rawget("outputCardNo"));
        appealInfo.setPaymentStatus(Integer.valueOf((String) data.rawget("paymentStatus")));
        appealInfo.setTransferAmount((String) data.rawget("transferAmount"));
        return appealInfo;
    }


    /**
     * 将账单lua数据转化为Bill对象,需要放到Bill.java里?
     *
     * @param data
     * @param appCode 交易查询的时候，appCode为空。否则其他情况，传对应的appCode进来
     * @return
     */
    public static Bill generateBill(LuaTable data, Bill.APPCODE appCode) {
        Bill bill = new Bill();
        if (data == null) {
            return bill;
        }
        if (null == appCode) {
            try {
                Double total = (Double) data.rawget("total");
                if (total != null) {
                    bill.setTotal(total);
                } else {
                    bill.setTotal(0);
                }
            } catch (Exception e) {
                bill.setTotal(0);
            }
            if (data.rawget("appcode") != null) {
                bill.setAppcode(data.rawget("appcode").toString());
            }
            if (data.rawget("appCode") != null) {
                bill.setAppcode(data.rawget("appCode").toString());
            }
            appCode = bill.getAppcode();
        } else {
            bill.setAppcode(appCode);
        }
        if (data == null) {
            return bill;
        }
        String transChannel = (String) data.rawget("transChannel");
        if (transChannel != null) {
            bill.setTransChannel(transChannel);
        } else {
            bill.setTransChannel("1");
        }
        // 帐帐通账户转账
        // 交易时间
        String transTime = (String) data.rawget("transTime");
        if (!TextUtils.isEmpty(transTime) && !transTime.equals("null")) {
            bill.setTransTime(transTime);
        } else {
            bill.setTransTime("");

        }
        // 交易描述.成功或失败的原因
        String transStatus = (String) data.rawget("transStatus");
        if (!TextUtils.isEmpty(transStatus) && !transStatus.equals("null")) {
            bill.setTransStatus(transStatus);
        } else {
            bill.setTransStatus("");
        }
        // 交易状态。1表示成功，0表示失败
        Object status = data.rawget("status");
        if (status != null && status instanceof Integer) {
            bill.setStatus(((Integer) status).intValue());
        } else if (status != null && status instanceof Double) {
            bill.setStatus(((Double) status).intValue());
        } else if (status != null && status instanceof String) {
            bill.setStatus(Integer.parseInt(status.toString() != null && status.toString().length() > 0 ? status.toString() : "0"));
        }
        // 交易流水号
        String transSN = (String) data.rawget("transSN");
        if (!TextUtils.isEmpty(transSN) && !transSN.equals("null")) {
            bill.setTransSN(transSN);
        } else {
            bill.setTransSN("");
        }
        String card = (String) data.rawget("cardNoOutFull");
        if (!TextUtils.isEmpty(card)) {
            try {
                if (appCode == Bill.APPCODE.TRANS) {
                    bill.setCardNoOut(CommonUtils.formattingCard(SecureManager.getInstance().des(card, 0, null)));
                } else if (appCode == Bill.APPCODE.MARKET_TRANS) {
                    bill.setCardNoOut(CommonUtils.formattingCard(SecureManager.getInstance().des(card, 0, null)));
                }
            } catch (StringIndexOutOfBoundsException e) {
                bill.setCardNoOut("");
                HPLog.e(HPLog.FDL_TAG, "card----" + e.getMessage());
            }
        }
        // 交易金额
        if (data != null && data.rawget("amount") != null) {
            bill.setAmount((Double.parseDouble(data.rawget("amount").toString())));
        }
        // 超级转账
        if (Bill.APPCODE.SUPER_TRANS == appCode) {
            String cardNoOut = (String) data.rawget("cardNoOutFull");
            bill.setCardNoOut(formattingCard(SecureManager.getInstance().des(cardNoOut, 0, null)));
            // 交易转出卡号--超级转账为cardNoOu
            if (TextUtils.isEmpty(cardNoOut)) {
                cardNoOut = (String) data.rawget("cardNoOut");
                bill.setCardNoOut(formattingCard(cardNoOut));
            }

            // 转入卡号
            // bill.setCardNoIn(CommonUtils.formatCard((String) data
            // .rawget("cardNoIn")));
            String cardNoIn = (String) data.rawget("cardNoIn");
            if (!TextUtils.isEmpty(cardNoIn)) {
                bill.setCardNoIn(CommonUtils.formattingCard(cardNoIn));
            }
            // 实付总额
            try {
                if (data.rawget("total") != null) {
                    bill.setTotal((Double.parseDouble(data.rawget("total").toString())));
                }
            } catch (Exception e) {
                bill.setTotal(0);
            }
            // 转账费率
            String fee = (String) data.rawget("3" + "");
            if (null != fee) {
                bill.setFee(Double.parseDouble(fee));
            } else {
                HPLog.e("Bill", "super transfer with no fee back!");
            }
        } else if (Bill.APPCODE.TRANS == appCode || Bill.APPCODE.MARKET_TRANS == appCode) {
            // 第三方支付和刷卡支付数据加密方式需要一致
            String obj = (String) data.rawget("shopName");
            if (!TextUtils.isEmpty(obj)) {
                bill.setShopName(SecureManager.getInstance().des(obj, 0, null));
            } else {
                bill.setShopName("");
            }
            obj = (String) data.rawget("merchantcode");
            if (!TextUtils.isEmpty(obj)) {
                bill.setMerchantCode(SecureManager.getInstance().des(obj, 0, null));
            } else {
                bill.setMerchantCode("");
            }

            obj = (String) data.rawget("issuerId");
            if (!TextUtils.isEmpty(obj)) {
                bill.setIssId(SecureManager.getInstance().des(obj, 0, null));
            } else {
                bill.setIssId("");
            }
            obj = (String) data.rawget("specialNumber");
            if (!TextUtils.isEmpty(obj)) {
                bill.setSpecialNumber(SecureManager.getInstance().des(obj, 0, null));
            } else {
                bill.setSpecialNumber("");
            }

            // obj = (String) data.rawget("cardNoOut");
            // if (!TextUtils.isEmpty(obj)) {
            // bill.setCardNoOut(obj);
            // } else {
            // bill.setCardNoOut("");
            // }

            Object desCsn = data.rawget("csn");
            if (null != desCsn) {
                bill.setTerminalNo(SecureManager.getInstance().des((String) desCsn, 0, null));

            }
            bill.setCardOrg((String) data.rawget("cardOrganization"));

            // 增加交易介质类型
            Object transMediaType = data.rawget("tranMediaType");
            if (null != transMediaType) {
                bill.setTranMediaType((String) transMediaType);

            }
        }
        // 交易查询详情
        Object o = data.rawget("imageUrl");
        if (null != o) {
            String imageUrl = null;
            String u = (String) o;
            if (!TextUtils.isEmpty(u) && ZZTConfig.ENV.REPLACEDOMAIN) {
                // FIXME 为后台增加访问图片，替换url
                if (u.indexOf("//") != -1) {
                    String[] splitTemp = u.split("//");
                    imageUrl = splitTemp[0] + "//";
                    imageUrl = imageUrl + ZZTConfig.ENV.SERVER + ":" + ZZTConfig.ENV.PORT;
                    if (splitTemp.length >= 1 && splitTemp[1].indexOf("/") != -1) {
                        String[] urlTemp2 = splitTemp[1].split("/");
                        if (urlTemp2.length > 1) {
                            for (int i = 1; i < urlTemp2.length; i++) {
                                imageUrl = imageUrl + "/" + urlTemp2[i];
                            }
                        }
                    }
                }
            } else {
                imageUrl = (String) o;
            }
            bill.setImageUrl(imageUrl);

        }
        o = data.rawget("detailUrl");
        if (null != o) {
            String imageUrl = null;
            String u = (String) o;
            if (!TextUtils.isEmpty(u) && ZZTConfig.ENV.REPLACEDOMAIN) {
                // FIXME 为后台增加访问图片，替换url
                if (u.indexOf("//") != -1) {
                    String[] splitTemp = u.split("//");
                    imageUrl = splitTemp[0] + "//";
                    imageUrl = imageUrl + ZZTConfig.ENV.SERVER + ":" + ZZTConfig.ENV.PORT;
                    if (splitTemp.length >= 1 && splitTemp[1].indexOf("/") != -1) {
                        String[] urlTemp2 = splitTemp[1].split("/");
                        if (urlTemp2.length > 1) {
                            for (int i = 1; i < urlTemp2.length; i++) {
                                imageUrl = imageUrl + "/" + urlTemp2[i];
                            }
                        }
                    }
                }
            } else {
                imageUrl = (String) o;
            }
            bill.setDetailUrl(imageUrl);

        }
        o = data.rawget("isOpen");
        if (null != o) {
            int isOpen = 0;
            if (o instanceof Integer) {
                isOpen = (Integer) o;
            } else if (o instanceof Double) {
                Double d = (Double) o;
                isOpen = d.intValue();
            }
            bill.setIsOpen(isOpen);

        }
        o = data.rawget("cardImageUrl");
        if (null != o) {
            String cardImageUrl = (String) o;
            bill.setCardImageUrl(cardImageUrl);
        }
        o = data.rawget("cardNoOutFull");
        if (null != o) {
            String cardNoOutFull = (String) o;
            bill.setCardNoOutFull(cardNoOutFull);
        }
        o = data.rawget("orderNo");
        if (null != o) {
            String orderNo = (String) o;
            bill.setOrderNo(orderNo);
        }
        o = data.rawget("transAccount");
        if (null != o) {
            String transAccount = (String) o;
            bill.setTransAccount(transAccount);

        }
        o = data.rawget("revokeStatus");
        if (o != null) {
            int revokeStatus = 0;
            if (o instanceof Integer) {
                revokeStatus = (Integer) o;
            } else if (o instanceof Double) {
                Double d = (Double) o;
                revokeStatus = d.intValue();
            }
            bill.setRovokeState(revokeStatus);

        }
        o = data.rawget("tradeType");
        if (o != null) {
            int tradeType = 0;
            if (o instanceof Integer) {
                tradeType = (Integer) o;
            } else if (o instanceof Double) {
                Double d = (Double) o;
                tradeType = d.intValue();
            }
            bill.setTradeType(tradeType);

        }
        o = data.rawget("isRevoke");
        if (o != null) {
            int isRevoke = 0;
            if (o instanceof Integer) {
                isRevoke = (Integer) o;
            } else if (o instanceof Double) {
                Double d = (Double) o;
                isRevoke = d.intValue();
            }
            bill.setIsRevoke(isRevoke);

        }
        o = data.rawget("appealStatus");
        if (o != null) {
//			int appealStatus = 0;
//			if (o instanceof Integer) {
//				appealStatus = (Integer) o;
//			} else if (o instanceof Double) {
//				Double d = (Double) o;
//				appealStatus = d.intValue();
//			}
            bill.setAppealStatus((String) o);
        }
        o = data.rawget("showAppealBtn");
        if (o != null) {
            int showAppealBtn = 0;
            if (o instanceof Integer) {
                showAppealBtn = (Integer) o;
            } else if (o instanceof Double) {
                Double d = (Double) o;
                showAppealBtn = d.intValue();
            }
            bill.setShowAppealBtn(showAppealBtn);
        }
        return bill;
    }


    /**
     * 将账单lua数据转化为Bill对象,需要放到Bill.java里?
     *
     * @param accountTransfer
     * @param appCode         交易查询的时候，appCode为空。否则其他情况，传对应的appCode进来
     * @return
     */
    public static Bill generateBill(AccountTransfer accountTransfer, Bill.APPCODE appCode) {
        Bill bill = new Bill();
        if (accountTransfer == null) {
            return bill;
        }
        if (null == appCode) {
            try {
                int total = CommonUtils.objectToInt(accountTransfer.getTotal());
                if (total != 0) {
                    bill.setTotal(total);
                } else {
                    bill.setTotal(0);
                }
            } catch (Exception e) {
                bill.setTotal(0);
            }
            if (accountTransfer.getAppcode() != null) {
                bill.setAppcode(accountTransfer.getAppcode());
            }
            if (accountTransfer.getAppCode() != null) {
                bill.setAppcode(accountTransfer.getAppCode());
            }
            appCode = bill.getAppcode();
        } else {
            bill.setAppcode(appCode);
        }
        String transChannel = accountTransfer.getTransChannel();
        if (transChannel != null) {
            bill.setTransChannel(transChannel);
        } else {
            bill.setTransChannel("1");
        }
        // 帐帐通账户转账
        // 交易时间
        String transTime = accountTransfer.getTransTime();
        if (!TextUtils.isEmpty(transTime) && !transTime.equals("null")) {
            bill.setTransTime(transTime);
        } else {
            bill.setTransTime("");

        }
        // 交易描述.成功或失败的原因
        String transStatus = accountTransfer.getTransStatus();
        if (!TextUtils.isEmpty(transStatus) && !transStatus.equals("null")) {
            bill.setTransStatus(transStatus);
        } else {
            bill.setTransStatus("");
        }
        // 交易状态。1表示成功，0表示失败
        Object status = accountTransfer.getStatus();
        if (status != null && status instanceof Integer) {
            bill.setStatus(((Integer) status).intValue());
        } else if (status != null && status instanceof Double) {
            bill.setStatus(((Double) status).intValue());
        } else if (status != null && status instanceof String) {
            bill.setStatus(Integer.parseInt(status.toString() != null && status.toString().length() > 0 ? status.toString() : "0"));
        }
        // 交易流水号
        String transSN = accountTransfer.getTransSN();
        if (!TextUtils.isEmpty(transSN) && !transSN.equals("null")) {
            bill.setTransSN(transSN);
        } else {
            bill.setTransSN("");
        }
        String card = accountTransfer.getCardNoOutFull();
        if (!TextUtils.isEmpty(card)) {
            try {
                if (appCode == Bill.APPCODE.TRANS) {
                    bill.setCardNoOut(CommonUtils.formattingCard(SecureManager.getInstance().des(card, 0, null)));
                } else if (appCode == Bill.APPCODE.MARKET_TRANS) {
                    bill.setCardNoOut(CommonUtils.formattingCard(SecureManager.getInstance().des(card, 0, null)));
                }
            } catch (StringIndexOutOfBoundsException e) {
                bill.setCardNoOut("");
                HPLog.e(HPLog.FDL_TAG, "card----" + e.getMessage());
            }
        }
        // 交易金额
        if (accountTransfer != null && accountTransfer.getAmount() != null) {
            bill.setAmount(Double.parseDouble(accountTransfer.getAmount()));
        }
        // 超级转账
        if (Bill.APPCODE.SUPER_TRANS == appCode) {
            String cardNoOut = accountTransfer.getCardNoOutFull();
            bill.setCardNoOut(formattingCard(SecureManager.getInstance().des(cardNoOut, 0, null)));
            // 交易转出卡号--超级转账为cardNoOu
            if (TextUtils.isEmpty(cardNoOut)) {
                cardNoOut = accountTransfer.getCardNoOut();
                bill.setCardNoOut(formattingCard(cardNoOut));
            }
            String cardNoIn = accountTransfer.getCardNoIn();
            if (!TextUtils.isEmpty(cardNoIn)) {
                bill.setCardNoIn(CommonUtils.formattingCard(cardNoIn));
            }
            bill.setTotal((Double.parseDouble(accountTransfer.getTotal())));
            // 转账费率
//            String fee = (String) data.rawget("3" +                    "");
//            if (null != fee) {
//                bill.setFee(Double.parseDouble(fee));
//            } else {
//                HPLog.e("Bill", "super transfer with no fee back!");
//            }
        } else if (Bill.APPCODE.TRANS == appCode || Bill.APPCODE.MARKET_TRANS == appCode) {
            bill.setShopName(SecureManager.getInstance().des(accountTransfer.getShopName(), 0, null));
            bill.setMerchantCode(SecureManager.getInstance().des(accountTransfer.getMerchantcode(), 0, null));
            bill.setIssId(SecureManager.getInstance().des(accountTransfer.getIsRevoke(), 0, null));
            bill.setSpecialNumber(SecureManager.getInstance().des(accountTransfer.getSpecialNumber(), 0, null));
            bill.setTerminalNo(SecureManager.getInstance().des(accountTransfer.getCsn(), 0, null));
            bill.setCardOrg(accountTransfer.getCardOrganization());
            bill.setTranMediaType(accountTransfer.getTranMediaType());
        }
        // 交易查询详情
        Object o = accountTransfer.getImageUrl();
        if (null != o) {
            String imageUrl = null;
            String u = (String) o;
            if (!TextUtils.isEmpty(u) && ZZTConfig.ENV.REPLACEDOMAIN) {
                // FIXME 为后台增加访问图片，替换url
                if (u.indexOf("//") != -1) {
                    String[] splitTemp = u.split("//");
                    imageUrl = splitTemp[0] + "//";
                    imageUrl = imageUrl + ZZTConfig.ENV.SERVER + ":" + ZZTConfig.ENV.PORT;
                    if (splitTemp.length >= 1 && splitTemp[1].indexOf("/") != -1) {
                        String[] urlTemp2 = splitTemp[1].split("/");
                        if (urlTemp2.length > 1) {
                            for (int i = 1; i < urlTemp2.length; i++) {
                                imageUrl = imageUrl + "/" + urlTemp2[i];
                            }
                        }
                    }
                }
            } else {
                imageUrl = (String) o;
            }
            bill.setImageUrl(imageUrl);

        }
        o = accountTransfer.getDetailUrl();
        if (null != o) {
            String imageUrl = null;
            String u = (String) o;
            if (!TextUtils.isEmpty(u) && ZZTConfig.ENV.REPLACEDOMAIN) {
                // FIXME 为后台增加访问图片，替换url
                if (u.indexOf("//") != -1) {
                    String[] splitTemp = u.split("//");
                    imageUrl = splitTemp[0] + "//";
                    imageUrl = imageUrl + ZZTConfig.ENV.SERVER + ":" + ZZTConfig.ENV.PORT;
                    if (splitTemp.length >= 1 && splitTemp[1].indexOf("/") != -1) {
                        String[] urlTemp2 = splitTemp[1].split("/");
                        if (urlTemp2.length > 1) {
                            for (int i = 1; i < urlTemp2.length; i++) {
                                imageUrl = imageUrl + "/" + urlTemp2[i];
                            }
                        }
                    }
                }
            } else {
                imageUrl = (String) o;
            }
            bill.setDetailUrl(imageUrl);

        }
        bill.setIsOpen(CommonUtils.objectToInt(accountTransfer.getIsOpen()));
        bill.setCardImageUrl(accountTransfer.getCardImageUrl());
        bill.setCardNoOutFull(accountTransfer.getCardNoOutFull());
        bill.setOrderNo(accountTransfer.getOrderNo());
        bill.setTransAccount(CommonUtils.formattingCard(accountTransfer.getTransAccount()));
        bill.setRovokeState(CommonUtils.objectToInt(accountTransfer.getRevokeStatus()));
        bill.setTradeType(CommonUtils.objectToInt(accountTransfer.getTradeType()));
        bill.setIsRevoke(CommonUtils.objectToInt(accountTransfer.getIsRevoke()));
        bill.setAppealStatus(accountTransfer.getAppcode());
        bill.setShowAppealBtn(CommonUtils.objectToInt(accountTransfer.getShowAppealBtn()));
        bill.setIsRevoke(CommonUtils.objectToInt(accountTransfer.getRevokeStatus()));
        bill.setShowSignStatus(CommonUtils.objectToInt(accountTransfer.getShowSignStatus()));

        return bill;
    }

    /**
     * 将账单lua数据转化为Bill对象,需要放到WithdrawRecordsBill.java里
     *
     * @param data
     * @return
     */
    public static WithdrawRecordsBill generateWithdrawRecordsBill(LuaTable data) {
        if (data == null) {
            return null;
        }
        WithdrawRecordsBill bill = new WithdrawRecordsBill();
        bill.setWithDrawApplyTime(CommonUtils.objectToString(data.rawget("rwdTime")));
        bill.setWithDrawstatus(CommonUtils.objectToString(data.rawget("rwdStatus")));
        bill.setmWithDrawDes(CommonUtils.objectToString(data.rawget("rwdDes")));
        bill.setApplyWithdrawAmount(CommonUtils.objectToString(data.rawget("rwdMoney")));
        if (WithdrawRecordsBill.STATUS_WD_SUCCESS == CommonUtils.objectToInt(bill.getWithDrawstatus())) {
            bill.setActualWithdrawAmount(CommonUtils.objectToString(data.rawget("wdMoney")));
        }
        return bill;
    }

    /**
     * 根据给定的Bitmap,返回byte数组。
     *
     * @param cache
     * @param max   限定byte数组大小。单位为KB
     * @return
     */
    public static byte[] getBitmapBytes(Bitmap cache, int max) {
        int maxByte = max * 1024;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        cache.compress(CompressFormat.JPEG, 99, baos);
        byte[] b = baos.toByteArray();
        try {
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        if (b.length <= maxByte) {
            return b;
        }
        // 原图超过最大限定，压缩到固定比例传
        int rate = (int) (Math.sqrt((maxByte * 1.0d) / b.length) * 100); // 这个方法并不确保一定比max小
        baos = new ByteArrayOutputStream();
        cache.compress(CompressFormat.JPEG, rate, baos);
        b = baos.toByteArray();
        try {
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return b;
    }

    public static byte[] resizeImage(Bitmap cache, int max) {
        Bitmap zooImg = zoomImg(cache, max);
        byte[] imgByte = getBitmapBytes(zooImg, 1);
        HPLog.i("IMAGE", "imageresize  newWith" + max);
        HPLog.i("IMAGE", "imageresize  rate" + 1);
        HPLog.i("IMAGE", "imageresize  length" + imgByte.length);
        if (zooImg != null) {
            zooImg.recycle();
        }
        return imgByte;
    }

    /**
     * 判断给定csn是不是新版刷卡器
     *
     * @param csn
     * @return
     */
    public static boolean isNewSwiper(String csn) {
        // 通过判断csn是不是16进制字符串来决定
        if (TextUtils.isEmpty(csn)) {
            return false;
        } else {
            boolean result = true;
            // csn = csn.toLowerCase(Locale.US);
            // for (int i=0; result && i < csn.length(); i++) {
            // if(-1 == charToByte(csn.charAt(i))) {
            // result = false;
            // }
            // }
            result = !csn.startsWith("CMBC");
            HPLog.i("Main", "isNewSwiper:" + result);
            return result;
        }

    }

    public static List<String> parseCard(String serviceInfo) {
        List<String> arrayList = new LinkedList<String>();
        if (serviceInfo != null && serviceInfo.length() > 4) {
            int length = Integer.parseInt(serviceInfo.substring(4, 6));
            HPLog.i("", "serviceInfo:" + serviceInfo + " length:" + serviceInfo.length() + "  cardlength: " + length);
            for (int i = 0; i < length; i++) {
                int end = (i + 1) * 20 + 6;
                if (end > serviceInfo.length()) {
                    end = serviceInfo.length();
                }
                arrayList.add(serviceInfo.substring(6 + i * 20, end).trim());
            }
        }
        return arrayList;
    }

    /**
     * --取得银行卡的BIN. ----参照utillib.lua而写
     */
    public static String getCardBin(String cardNo) {
        if (TextUtils.isEmpty(cardNo)) {
            return "";
        }
        int len = cardNo.length();
        if (len < ZZTConstant.CARDNO_MIN_LEN) {
            return "";
        } else {
            return cardNo.substring(0, ZZTConstant.CARDBINPOS + 1) + String.valueOf(len);
        }
    }

    /**
     * 加密卡号----参照utillib.lua而写
     *
     * @return
     */
    public static String encCardNo(String cardNo) {
        if (TextUtils.isEmpty(cardNo)) {
            return "";
        }
        int len = cardNo.length();
        while (len < ZZTConstant.CARDNO_MIN_LEN + 1) {
            cardNo = cardNo + " ";
            len = cardNo.length();
        }
        String result = SecureManager.getInstance().des(cardNo.substring(0, 8), 1, null) + SecureManager.getInstance().des(cardNo.substring(8, 16), 1, null);
        // 账号长度大于16
        if ((ZZTConstant.CARDNO_MIN_LEN + 1) < len) {
            String temp = cardNo + "         ";
            temp = temp.substring(0, 24);
            result = result + SecureManager.getInstance().des(temp.substring(16, 24), 1, null);
        }
        return result;
    }

    /**
     * 字符串转16进制
     *
     * @param str
     * @return
     */
    public static String string2Hex(String str) {
        char[] chars = str.toCharArray();
        StringBuffer hex = new StringBuffer();

        for (int i = 0; i < chars.length; i++) {
            hex.append(Integer.toHexString((int) chars[i]));
        }
        return hex.toString();
    }

    /*
     * 将16进制数字解码成字符串,适用于所有字搜索符（包括中文）
     */
    public static String hex2String(String bytes) {
        String hexString = "0123456789ABCDEF";
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length() / 2);
        // 将每2位16进制整数组装成一个字节
        for (int i = 0; i < bytes.length(); i += 2)
            baos.write((hexString.indexOf(bytes.charAt(i)) << 4 | hexString.indexOf(bytes.charAt(i + 1))));
        return new String(baos.toByteArray());
    }

    public static String bytesToHexString(byte[] src) {
        if (src == null || src.length <= 0) {
            return null;
        }
        try {
            StringBuilder stringBuilder = new StringBuilder(2 * src.length);
            for (int i = 0; i < src.length; i++) {
                int v = src[i] & 0xFF;
                String hv = Integer.toHexString(v);
                if (hv.length() < 2) {
                    stringBuilder.append(0);
                }
                stringBuilder.append(hv);
            }
            return stringBuilder.toString();
        } catch (Exception outOfMemoryError) {
            HPLog.e("", "bytes length:" + src.length, outOfMemoryError);
        }
        return null;
    }

    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        hexString = hexString.toUpperCase(Locale.US);
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    public static byte[] convertBitmapToByteArray(Bitmap b) {
        if (null == b) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        b.compress(CompressFormat.JPEG, 100, baos);
        byte[] result = baos.toByteArray();
        try {
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static String convertBitmapToString(Bitmap b) {
        if (null == b) {
            return null;
        }
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        b.compress(CompressFormat.JPEG, 100, baos);
        String result = bytesToHexString(baos.toByteArray());
        try {
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }

    public static Bitmap convertStringToBitmap(String s) {
        if (null == s) {
            return null;
        }
        try {
            byte[] byteArray = hexStringToBytes(s);
            return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);
        } catch (Exception e) {
            e.fillInStackTrace();
            return null;
        } finally {

        }
    }

    /**
     * text是否以arrays.xml中的资源id的数组中字符串开头
     *
     * @param id
     * @param text
     * @return
     */
    public static boolean inStringArray(Resources resource, int id, String text) {
        try {
            String array[] = resource.getStringArray(id);
            int length = array.length;
            for (int i = 0; i < length; i++) {
                if (text.startsWith(array[i])) {
                    return true;
                }
            }
        } catch (Exception e) {

        }
        return false;
    }

    /*
     * function formatCardNo(cardNo) if cardNo==nil or cardNo=="" then return
     * end local star,len="",string.len(cardNo) for i=1,8,1 do if (i == 5) then
     * star = star .. " " end star = star .. "*" end return
     * string.sub(cardNo,1,4) .. " " .. star .. " " .. string.sub(cardNo,len-3)
     * end
     */
    public static String convertCardNo2Enc(String accountNo) {
        if (TextUtils.isEmpty(accountNo)) {
            return "";
        }
        String star = "";
        int len = accountNo.length();
        for (int i = 0; i < 8; i++) {
            if (i == 4) {
                star = star + " ";
            }
            star = star + "*";
        }
        return accountNo.substring(0, 4) + " " + star + " " + accountNo.substring(len - 4);
    }

    public static String formatPhone(String phone) {
        String start = phone.substring(0, 3);
        String end = phone.substring(phone.length() - 4);
        return start + " **** " + end;
    }

    /**
     * 格式化银行卡
     *
     * @param card
     * @return
     */
    public static String formatCard(String card) {
        StringBuffer sb = new StringBuffer();
        card = card.replace(" ", "");

        int index = 0;
        while ((index + 4) < card.length()) {
            sb.append((card.substring(index, index + 4) + " "));
            index += 4;
        }
        sb.append((card.substring(index, card.length())));
        return sb.toString();
    }

    /**
     * 格式化銀行卡 如：1234 **** **** 5678
     *
     * @param card
     * @return
     */
    public static String formattingCard4_4(String card) {
        if (TextUtils.isEmpty(card)) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        card = card.replace(" ", "");
        int index = 0;
        String start = card.substring(index, index + 4);
        String end = card.substring(card.length() - 4);
        return start + " " + "**** ****" + " " + end;
    }

    /**
     * 格式化銀行卡 如：**** **** **** 5678
     *
     * @param card
     * @return
     */
    public static String formattingCard(String card) {
        if (TextUtils.isEmpty(card)) {
            return null;
        }
        StringBuffer sb = new StringBuffer();
        card = card.replace(" ", "");
        int index = 0;
        String start = card.substring(index, index + 4);
        String end = card.substring(card.length() - 4);
        return "**** **** ****" + " " + end;
    }

    public static String  formattingCertNo4_2(String certNo){
        if (TextUtils.isEmpty(certNo)) {
            return null;
        }
        String start = certNo.substring(0, 4);
        String end = certNo.substring(certNo.length() - 2);
        return start + "************" + end;

    }


    /*********************************** 身份证验证开始 ****************************************/
    /**
     * 身份证号码验证 1、号码的结构 公民身份号码是特征组合码，由十七位数字本体码和一位校验码组成。排列顺序从左至右依次为：六位数字地址码，
     * 八位数字出生日期码，三位数字顺序码和一位数字校验码。 2、地址码(前六位数）
     * 表示编码对象常住户口所在县(市、旗、区)的行政区划代码，按GB/T2260的规定执行。 3、出生日期码（第七位至十四位）
     * 表示编码对象出生的年、月、日，按GB/T7408的规定执行，年、月、日代码之间不用分隔符。 4、顺序码（第十五位至十七位）
     * 表示在同一地址码所标识的区域范围内，对同年、同月、同日出生的人编定的顺序号， 顺序码的奇数分配给男性，偶数分配给女性。 5、校验码（第十八位数）
     * （1）十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0, ... , 16 ，先对前17位数字的权求和
     * Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4
     * 2 （2）计算模 Y = mod(S, 11) （3）通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0
     * X 9 8 7 6 5 4 3 2
     */
    public static final String[] ValCodeArr = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
    public static final String[] Wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
    // 身份证的最小出生日期,1900年1月1日
    private final static int NEW_CARD_NUMBER_LENGTH = 18;

    /**
     * 功能：身份证的有效验证
     *
     * @param IDStr        身份证号
     * @param isValidate15 是否需要校验15位身份证
     * @return 有效：返回null 无效：返回String信息
     * @throws ParseException
     */
    public static String IDCardValidate(String IDStr, boolean isValidate15) throws ParseException {
        IDStr = IDStr.toLowerCase(Locale.US);

        String Ai = "";
        // ================ 号码的长度 15位或18位 ================
        if ((isValidate15 == false || IDStr.length() != 15) && IDStr.length() != 18) {
            return isValidate15 == true ? "身份证号码长度应该为15位或18位。" : "身份证号码长度应该为18位。";
        }
        // else{//如果是15位旧身份证，则根据算法补全
        // if(IDStr.length()==15){
        // IDStr=contertToNewCardNumber(IDStr);
        // }
        // }
        // =======================(end)========================

        // ================ 数字 除最后以为都为数字 ================
        if (IDStr.length() == 18) {
            Ai = IDStr.substring(0, 17);
        } else if (IDStr.length() == 15) {
            Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15);
        }
        if (isNumeric(Ai) == false) {
            return "身份证15位号码都应为数字 ; 18位号码除最后一位外，都应为数字。";
        }
        // =======================(end)========================

        // ================ 出生年月是否有效 ================
        String strYear = Ai.substring(6, 10);// 年份
        String strMonth = Ai.substring(10, 12);// 月份
        String strDay = Ai.substring(12, 14);// 月份
        if (DateUtils.isDate(strYear + "-" + strMonth + "-" + strDay) == false) {
            return "身份证生日无效。";
        }
        GregorianCalendar gc = new GregorianCalendar();
        SimpleDateFormat s = new SimpleDateFormat("yyyy-MM-dd");
        if ((gc.get(Calendar.YEAR) - Integer.parseInt(strYear)) > 150 || (gc.getTime().getTime() - s.parse(strYear + "-" + strMonth + "-" + strDay).getTime()) < 0) {
            return "身份证生日不在有效范围。";
        }
        if (Integer.parseInt(strMonth) > 12 || Integer.parseInt(strMonth) == 0) {
            return "身份证月份无效";
        }
        if (Integer.parseInt(strDay) > 31 || Integer.parseInt(strDay) == 0) {
            return "身份证日期无效";
        }
        // =====================(end)=====================

        // ================ 地区码时候有效 ================
        Hashtable<String, String> h = GetAreaCode();
        if (h.get(Ai.substring(0, 2)) == null) {
            return "身份证地区编码错误。";
        }
        // ==============================================

        // ================ 判断最后一位的值 ================
        int TotalmulAiWi = 0;
        for (int i = 0; i < 17; i++) {
            TotalmulAiWi = TotalmulAiWi + Integer.parseInt(String.valueOf(Ai.charAt(i))) * Integer.parseInt(Wi[i]);
        }
        int modValue = TotalmulAiWi % 11;
        String strVerifyCode = ValCodeArr[modValue];
        Ai = Ai + strVerifyCode;

        if (IDStr.length() == 18) {
            if (Ai.equals(IDStr) == false) {
                return "身份证无效，不是合法的身份证号码";
            }
        } else {
            return null;
        }
        // =====================(end)=====================
        return null;
    }

    /**
     * 功能：设置地区编码
     *
     * @return Hashtable 对象
     */
    private static Hashtable<String, String> GetAreaCode() {
        Hashtable<String, String> hashtable = new Hashtable<String, String>();
        hashtable.put("11", "北京");
        hashtable.put("12", "天津");
        hashtable.put("13", "河北");
        hashtable.put("14", "山西");
        hashtable.put("15", "内蒙古");
        hashtable.put("21", "辽宁");
        hashtable.put("22", "吉林");
        hashtable.put("23", "黑龙江");
        hashtable.put("31", "上海");
        hashtable.put("32", "江苏");
        hashtable.put("33", "浙江");
        hashtable.put("34", "安徽");
        hashtable.put("35", "福建");
        hashtable.put("36", "江西");
        hashtable.put("37", "山东");
        hashtable.put("41", "河南");
        hashtable.put("42", "湖北");
        hashtable.put("43", "湖南");
        hashtable.put("44", "广东");
        hashtable.put("45", "广西");
        hashtable.put("46", "海南");
        hashtable.put("50", "重庆");
        hashtable.put("51", "四川");
        hashtable.put("52", "贵州");
        hashtable.put("53", "云南");
        hashtable.put("54", "西藏");
        hashtable.put("61", "陕西");
        hashtable.put("62", "甘肃");
        hashtable.put("63", "青海");
        hashtable.put("64", "宁夏");
        hashtable.put("65", "新疆");
        hashtable.put("71", "台湾");
        hashtable.put("81", "香港");
        hashtable.put("82", "澳门");
        hashtable.put("91", "国外");
        return hashtable;
    }

    /**
     * 功能：判断字符串是否为数字
     *
     * @param str
     * @return
     */
    private static boolean isNumeric(String str) {
        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);
        return isNum.matches();
    }

    /**
     * --判断卡号是否合法
     *
     * @param cardNo
     * @return
     */
    public static boolean isLegalCard(String cardNo) {
        if (TextUtils.isEmpty(cardNo) || !TextUtils.isDigitsOnly(cardNo) || cardNo.length() < 11) {
            return false;
        }
        char[] cCardNo = cardNo.toCharArray();
        boolean allZero = true;
        for (int j = 0; j < cCardNo.length; j++) {
            if ('0' != cCardNo[j]) {
                allZero = false;
                break;
            }
        }
        // 全零，不是合法卡号
        if (allZero) {
            return false;
        }
        for (int pos = 1; pos <= 2; pos++) {
            int count = 0;
            boolean bMulti = true;
            for (int i = cCardNo.length - 1 - pos; i >= 0; i--) {
                if (bMulti) {
                    int multi = (cCardNo[i] - '0') * 2;
                    if (multi > 9) {
                        multi = multi - 9;
                    }
                    count += multi;
                } else {
                    count += (cCardNo[i] - '0');
                }
                bMulti = !bMulti;
            }
            int addition = Integer.parseInt(cardNo.substring(cardNo.length() - pos, cardNo.length()));
            if ((count + addition) % 10 == 0) {
                return true;
            }
        }
        HPLog.e("isLegalCard", cardNo + ":false");
        return false;
    }

    /**
     * 把15位身份证号码转换到18位身份证号码<br>
     * 15位身份证号码与18位身份证号码的区别为：<br>
     * 1、15位身份证号码中，"出生年份"字段是2位，转换时需要补入"19"，表示20世纪<br>
     * 2、15位身份证无最后一位校验码。18位身份证中，校验码根据根据前17位生成
     *
     * @param oldCardNumber
     * @return
     */
    private static String contertToNewCardNumber(String oldCardNumber) {
        StringBuilder buf = new StringBuilder(NEW_CARD_NUMBER_LENGTH);
        buf.append(oldCardNumber.substring(0, 6));
        buf.append("19");
        buf.append(oldCardNumber.substring(6));
        buf.append(calculateVerifyCode(buf));
        return buf.toString();
    }

    /**
     * 计算最后一位校验码
     *
     * @param cardNumber
     * @return
     */
    private static String calculateVerifyCode(CharSequence cardNumber) {
        int sum = 0;
        for (int i = 0; i < NEW_CARD_NUMBER_LENGTH - 1; i++) {
            char ch = cardNumber.charAt(i);
            sum += (ch - '0') * Integer.parseInt(Wi[i]);
        }
        return ValCodeArr[sum % 11];
    }

    /**
     * 判断GPS是否开启，GPS或者AGPS开启一个就认为是开启的
     *
     * @param context
     * @return true 表示开启
     */
    public static final boolean isLocationServiceOpen(final Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        // 通过GPS卫星定位，定位级别可以精确到街（通过24颗卫星定位，在室外和空旷的地方定位准确、速度快）
        boolean gps = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        // 通过WLAN或移动网络(3G/2G)确定的位置（也称作AGPS，辅助GPS定位。主要用于在室内或遮盖物（建筑群或茂密的深林等）密集的地方定位）
        boolean network = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
        return gps || network;
    }

    public static boolean removePics() {
        File folder = getAccessDir();
        for (File f : folder.listFiles(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String filename) {
                HPLog.i("removePics", "accept filename:" + filename);
                return filename.startsWith("pic") && filename.endsWith("jpg");
            }
        })) {
            f.delete();
        }
        return true;
    }

    public static File getAccessDir() {
        // FIXME 判断在外部存储还是内部存储。
        String strStorageState = android.os.Environment.getExternalStorageState();
        if (android.os.Environment.MEDIA_MOUNTED.equals(strStorageState)) {
            File f = Environment.getExternalStorageDirectory();
            File picDir = new File(f.getAbsolutePath() + File.separator + "ZZTongActivity");
            if (picDir.exists()) {
                return picDir;
            } else {
                // 如果创建目录成功，返回该目录，否则返回SDK根目录
                if (picDir.mkdirs()) {
                    return picDir;
                } else {
                    return f;
                }
            }
        } else {
            return ZZTApplication.getApp().getApplicationContext().getFilesDir().getAbsoluteFile();
        }

    }

    public static Uri randomUri(File directory) {
        Uri uri = Uri.fromFile(randomFile(directory));
        return uri;
    }

    public static File randomFile(File directory) {
        File file;
        Random r = new Random();
        long rand = r.nextLong();
        do {
            file = new File(directory, "pic" + rand + ".jpg");
            rand++;
        } while (file.exists());
        return file;
    }

    public static boolean isNumAndChar(String str) {
        if (TextUtils.isEmpty(str)) {
            return false;
        }
        char[] s = str.toLowerCase(Locale.US).toCharArray();
        boolean hasDigit = false;
        boolean hasChar = false;
        boolean hasOther = false;
        for (int i = 0; i < s.length; i++) {
            if ('0' <= s[i] && '9' >= s[i]) {
                hasDigit = true;
                continue;
            }
            if ('a' <= s[i] && 'z' >= s[i]) {
                hasChar = true;
                continue;
            }
            hasOther = true;
            break;
        }
        return hasDigit && hasChar && !hasOther;
    }

    /**
     * 帅济满。用于快速创建，在noResponseTime时间内，点击无响应的View ClickListener
     *
     * @param noResponseTime 以ms为单位。在这段时间内，再次点击不响应
     * @param listener       响应的listener
     * @return
     */
    public static View.OnClickListener createNoQuickResponseViewListener(final int noResponseTime, final View.OnClickListener listener) {
        return new View.OnClickListener() {
            private long mLastClickTime = 0;

            @Override
            public void onClick(View v) {
                // 避免多次点击
                if (SystemClock.elapsedRealtime() - mLastClickTime < noResponseTime) {
                    return;
                }
                mLastClickTime = SystemClock.elapsedRealtime();
                listener.onClick(v);
            }
        };
    }

    public static OnItemClickListener createNoQuickResponseViewListener(final int noResponseTime, final OnItemClickListener listener) {
        return new OnItemClickListener() {
            private long mLastClickTime = 0;

            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                // 避免多次点击
                if (SystemClock.elapsedRealtime() - mLastClickTime < noResponseTime) {
                    return;
                }
                mLastClickTime = SystemClock.elapsedRealtime();
                listener.onItemClick(parent, view, position, id);
            }
        };
    }

    /***
     * 李国红 检验手机号码是否合法
     *
     * @param mobiles
     * @return
     */
    public static boolean isMobileNum(String mobiles) {
        if (mobiles == null || mobiles.trim().length() == 0) return false;
        if (mobiles.length() != ZZTConstant.PHONE_NUM_LENGTH) {
            return false;
        }
        if (!isMobileNO1(mobiles)) {
            return false;
        }
        return '1' == mobiles.charAt(0);
    }

    public static boolean isMobileNO1(String mobiles) {
        String regExp = "^[1][0-9]{10}$";
        Pattern p = Pattern.compile(regExp);
        Matcher m = p.matcher(mobiles);
        return m.matches();
    }

    public static boolean isShopNameLegal(String shopName) {
        return !TextUtils.isEmpty(shopName) && shopName.length() <= ZZTConstant.MAX_SHOP_NAME_LENGTH && !isHaveSpecialCharacter(shopName, regShopEx);
    }

    public static boolean isLegalExpireDate(String expireDate) {
        String regex = "^\\d{4}$";
        boolean isLegal = Pattern.matches(regex, expireDate);
        return isLegal;
    }

    /**
     * 格式化金额，将20位的银联金额格式变为普通元角分格式。
     *
     * @param amount 需要格式化的金额。
     * @return 格式化后的金额。
     */
    public static final String formatAmount(String amount) {
        String newAmount = new String();

        int len = amount.length();
        int index = -1;
        for (int i = 0; i < len; i++) {
            char c = amount.charAt(i);
            if (c != '0') {
                index = i;
                break;
            }
        }

        if (index == -1) return "0.00";

        newAmount = amount.substring(index);
        if (newAmount.length() < 3) {
            newAmount = ("00" + newAmount);
            newAmount = newAmount.substring(newAmount.length() - 3);
        }

        String newAmount0 = newAmount.substring(newAmount.length() - 2);
        String newAmount1 = newAmount.substring(0, newAmount.length() - 2);

        newAmount = newAmount1 + "." + newAmount0;

        return newAmount;
    }

    /**
     * 检查字符串中是否有特殊字符
     *
     * @param str
     * 需要检查的字符串。
     * @return 检查结果。
     */
    // shopName can have {. , ( ) （ ）}
    private static String regShopEx = "[`~!@#$%^&*+=|{}':;'\\[\\]<>/?~！@#￥%……&*——+|{}【】‘；：”“’。，、？]";

    private static boolean isHaveSpecialCharacter(String str, String regEx) {
        if (TextUtils.isEmpty(str)) {
            return false;
        }
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.find();
    }

    /**
     * 图片缩放
     */
    public static Bitmap zoomImg(Bitmap bm, int newWidth) {
        // 获得图片的宽高
        int width = bm.getWidth();
        int height = bm.getHeight();
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        // float scaleHeight = ((float) newHeight) / height;
        // 取得想要缩放的matrix参数
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleWidth);
        // 得到新的图片
        Bitmap newbm;
        try {
            newbm = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, true);
        } catch (Exception outOfMemoryError) {
            newbm = bm;
            HPLog.i("CommonUtils", "CommonUtils---->zoomImg-->line-1331:" + outOfMemoryError.toString());
        }
        return newbm;
    }

    /**
     * @功能: BCD码转为10进制串(阿拉伯数据)
     * @参数: BCD码
     * @结果: 10进制串
     */
    public static String bcd2Str(byte[] bytes) {
        StringBuffer temp = new StringBuffer(bytes.length * 2);
        for (int i = 0; i < bytes.length; i++) {
            temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
            temp.append((byte) (bytes[i] & 0x0f));
        }
        return temp.toString().substring(0, 1).equalsIgnoreCase("0") ? temp.toString().substring(1) : temp.toString();
    }

    /**
     * @功能: 10进制串转为BCD码
     * @参数: 10进制串
     * @结果: BCD码
     */
    public static byte[] str2Bcd(String asc) {
        int len = asc.length();
        int mod = len % 2;
        if (mod != 0) {
            asc = "0" + asc;
            len = asc.length();
        }
        byte abt[] = new byte[len];
        if (len >= 2) {
            len = len / 2;
        }
        byte bbt[] = new byte[len];
        abt = asc.getBytes();
        int j, k;
        for (int p = 0; p < asc.length() / 2; p++) {
            if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
                j = abt[2 * p] - '0';
            } else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
                j = abt[2 * p] - 'a' + 0x0a;
            } else {
                j = abt[2 * p] - 'A' + 0x0a;
            }
            if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
                k = abt[2 * p + 1] - '0';
            } else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
                k = abt[2 * p + 1] - 'a' + 0x0a;
            } else {
                k = abt[2 * p + 1] - 'A' + 0x0a;
            }
            int a = (j << 4) + k;
            byte b = (byte) a;
            bbt[p] = b;
        }
        return bbt;
    }

    public static String formatMoneyToPos(String money, int totalLen) {
        String zero = "";
        for (int i = 0; i < totalLen; i++) {
            zero += "0";
        }
        String moneyStr = money;
        return zero.substring(0, totalLen - moneyStr.length()) + moneyStr;
    }

    /**
     * 两点求距离
     */
    public static double getSqrt(double x, double x2, double y, double y2) {
        return Math.sqrt(Math.abs(x - x2) * Math.abs(x - x2) + Math.abs(y - y2) * Math.abs(y - y2));
    }

    public static int dp2px(float dpValue) {

        return (int) (dpValue * Heart.density + 0.5f);
    }

    public static int px2dp(float pxValue) {
        return (int) (pxValue / Heart.density + 0.5f);
    }

    /**
     * 格式化金额 50.0-->50
     *
     * @param moneystr
     * @return
     */
    public static String formatMoeny(String moneystr) {
        String result = moneystr.substring(0, moneystr.length() - 2);
        return result;
    }

    public static String formatYearMMDay(String time) {
        String year = "";
        String mm = "";
        String day = "";
        if (!TextUtils.isEmpty(time)) {
            year = time.substring(0, 4);
            mm = time.substring(4, 6);
            day = time.substring(6, 8);
        }
        return year + "/" + mm + "/" + day;
    }

    public static String formatTime(String time) {
        String year = "";
        String mm = "";
        String day = "";
        String hh = "";
        String ff = "";
        String ms = "";
        if (!TextUtils.isEmpty(time)) {
            year = time.substring(0, 4);
            mm = time.substring(4, 6);
            day = time.substring(6, 8);
            hh = time.substring(8, 10);
            ff = time.substring(10, 12);
            ms = time.substring(12, 14);
        }
        return year + "/" + mm + "/" + day + "  " + hh + ":" + ff + ":" + ms;
    }

    public static File getAutoExistFile(File directory, String fileName) {
        File file = new File(directory, fileName);
        return file;
    }

    public static boolean checkExpireDate(String plainExpireDate) {
        return !TextUtils.isEmpty(plainExpireDate) && plainExpireDate.length() >= 4;
    }

    public static File getAccessImgDir() {
        // FIXME 判断在外部存储还是内部存储。
        String strStorageState = android.os.Environment.getExternalStorageState();
        if (android.os.Environment.MEDIA_MOUNTED.equals(strStorageState)) {
            File f = Environment.getExternalStorageDirectory();
            File picDir = new File(f.getAbsolutePath() + File.separator + "ZZTongActivity" + File.separator + "cardImg");
            if (picDir.exists()) {
                return picDir;
            } else {
                // 如果创建目录成功，返回该目录，否则返回SDK根目录
                if (picDir.mkdirs()) {
                    return picDir;
                } else {
                    return f;
                }
            }
        } else {
            return ZZTApplication.getApp().getApplicationContext().getFilesDir().getAbsoluteFile();
        }
    }

    /**
     * 判断qq是否可用
     *
     * @param context
     * @return
     */
    public static boolean isQQClientAvailable(Context context) {
        final PackageManager packageManager = context.getPackageManager();
        List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
        if (pinfo != null) {
            for (int i = 0; i < pinfo.size(); i++) {
                String pn = pinfo.get(i).packageName;
                if (pn.equals("com.tencent.mobileqq")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断支付宝是否可用
     *
     * @param context
     * @return
     */
    public static boolean isAlipayClientAvailable(Context context) {
        final PackageManager packageManager = context.getPackageManager();
        List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
        if (pinfo != null) {
            for (int i = 0; i < pinfo.size(); i++) {
                String pn = pinfo.get(i).packageName;
                HPLog.i(HPLog.YL_TAG, "package name: " + pn);
                if (pn.equals("com.eg.android.AlipayGphone")) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 判断支付宝是否可用
     *
     * @param context
     * @return
     */
    public static boolean isWeixinClientAvailable(Context context) {
        final PackageManager packageManager = context.getPackageManager();
        List<PackageInfo> pinfo = packageManager.getInstalledPackages(0);
        if (pinfo != null) {
            for (int i = 0; i < pinfo.size(); i++) {
                String pn = pinfo.get(i).packageName;
                if (pn.equals("com.tencent.mm")) {
                    return true;
                }
            }
        }
        return false;
    }


//    public static boolean openWeixinClient(Context context) {
//
//        Intent intent =context.getPackageManager().getLaunchIntentForPackage("com.tencent.mm");
//        startActivit(intent);
//    }

    public static String getIPAddress(boolean useIPv4) {
        try {
            List<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
            for (NetworkInterface intf : interfaces) {
                List<InetAddress> addrs = Collections.list(intf.getInetAddresses());
                for (InetAddress addr : addrs) {
                    if (!addr.isLoopbackAddress()) {
                        String sAddr = addr.getHostAddress();
                        // boolean isIPv4 =
                        // InetAddressUtils.isIPv4Address(sAddr);
                        boolean isIPv4 = sAddr.indexOf(':') < 0;

                        if (useIPv4) {
                            if (isIPv4) return sAddr;
                        } else {
                            if (!isIPv4) {
                                int delim = sAddr.indexOf('%'); // drop ip6 zone
                                // suffix
                                return delim < 0 ? sAddr.toUpperCase() : sAddr.substring(0, delim).toUpperCase();
                            }
                        }
                    }
                }
            }
        } catch (Exception ex) {
        } // for now eat exceptions
        return "";
    }

    /**
     * 获取url参数Map
     *
     * @param url
     * @return
     */
    public static Map<String, String> getUrlParamsMap(String url) {
        Map<String, String> map = null;
        if (url != null) if (url.indexOf("?") > -1) {
            url = url.substring(url.indexOf("?") + 1);
        }
        if (url.indexOf("&") > -1 && url.indexOf("=") > -1) {
            map = new HashMap<String, String>();
            String[] arrTemp = url.split("&");
            for (String str : arrTemp) {
                String[] qs = str.split("=");
                map.put(qs[0], qs[1]);
            }
        }
        return map;
    }

    /**
     * 获取未安装Apk的签名
     *
     * @param apkPath
     * @return
     */
    public static Signature getNoInstalledApkSignature(String apkPath) {
        String PATH_PackageParser = "android.content.pm.PackageParser";
        try {
            // apk包的文件路径
            // 这是一个Package 解释器, 是隐藏的
            // 构造函数的参数只有一个, apk文件的路径
            Class<?> pkgParserCls = Class.forName(PATH_PackageParser);
            Class<?>[] typeArgs = new Class[1];
            typeArgs[0] = String.class;
            Object[] valueArgs = new Object[1];
            valueArgs[0] = apkPath;
            Object pkgParser;
            if (Build.VERSION.SDK_INT > 19) {
                pkgParser = pkgParserCls.newInstance();
            } else {
                Constructor constructor = pkgParserCls.getConstructor(typeArgs);
                pkgParser = constructor.newInstance(valueArgs);
            }
            // 这个是与显示有关的, 里面涉及到一些像素显示等等, 我们使用默认的情况
            DisplayMetrics metrics = new DisplayMetrics();
            metrics.setToDefaults();
            // PackageParser.Package mPkgInfo = packageParser.parsePackage(new
            // File(apkPath), apkPath,
            // metrics, 0);
            Object pkgParserPkg = null;
            if (Build.VERSION.SDK_INT > 19) {
                valueArgs = new Object[2];
                valueArgs[0] = new File(apkPath);
                valueArgs[1] = PackageManager.GET_SIGNATURES;
                Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", typeArgs);
                pkgParser_parsePackageMtd.setAccessible(true);
                typeArgs = new Class[2];
                typeArgs[0] = File.class;
                typeArgs[1] = int.class;
                pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, valueArgs);
            } else {
                typeArgs = new Class[4];
                typeArgs[0] = File.class;
                typeArgs[1] = String.class;
                typeArgs[2] = DisplayMetrics.class;
                typeArgs[3] = int.class;
                Method pkgParser_parsePackageMtd = pkgParserCls.getDeclaredMethod("parsePackage", typeArgs);
                pkgParser_parsePackageMtd.setAccessible(true);
                valueArgs = new Object[4];
                valueArgs[0] = new File(apkPath);
                valueArgs[1] = apkPath;
                valueArgs[2] = metrics;
                valueArgs[3] = PackageManager.GET_SIGNATURES;
                pkgParserPkg = pkgParser_parsePackageMtd.invoke(pkgParser, valueArgs);
            }
            typeArgs = new Class[2];
            typeArgs[0] = pkgParserPkg.getClass();
            typeArgs[1] = int.class;
            Method pkgParser_collectCertificatesMtd = pkgParserCls.getDeclaredMethod("collectCertificates", typeArgs);
            valueArgs = new Object[2];
            valueArgs[0] = pkgParserPkg;
            valueArgs[1] = PackageManager.GET_SIGNATURES;
            pkgParser_collectCertificatesMtd.invoke(pkgParser, valueArgs);
            // 应用程序信息包, 这个公开的, 不过有些函数, 变量没公开
            Field packageInfoFld = pkgParserPkg.getClass().getDeclaredField("mSignatures");
            Signature[] info = (Signature[]) packageInfoFld.get(pkgParserPkg);
            return info[0];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取已安装apk签名
     *
     * @param context
     * @param packageName
     * @return
     */
    public static Signature getInstallPackageSignature(Context context, String packageName) {
        if ((packageName == null) || (packageName.length() == 0)) {
            return null;
        }
        PackageManager pkgMgr = context.getPackageManager();
        PackageInfo info = null;
        try {
            info = pkgMgr.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
            return info.signatures[0];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getMD5(Signature temp) {
        try {
            MessageDigest localMessageDigest_md5 = MessageDigest.getInstance("MD5");
            localMessageDigest_md5.update(temp.toByteArray());
            String str2_md5 = CommonUtils.bytesToHexString(localMessageDigest_md5.digest()).toUpperCase();
            return str2_md5;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getSHA1(Signature temp) {
        try {
            MessageDigest localMessageDigest_sha1 = MessageDigest.getInstance("SHA1");
            localMessageDigest_sha1.update(temp.toByteArray());
            String str2_sha1 = CommonUtils.bytesToHexString(localMessageDigest_sha1.digest()).toUpperCase();
            return str2_sha1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * @param object
     * @return object 转换为String
     */
    public static String objectToString(Object object) {
        if (object == null) return null;
        if (object != null) {
            if (object instanceof Double) {
                return String.valueOf(((Double) object).doubleValue());
            } else if (object instanceof String) {
                return (String) object;
            } else if (object instanceof Integer) {
                return String.valueOf(((Integer) object).intValue());
            } else if (object instanceof Float) {
                return String.valueOf(((Float) object).floatValue());
            }
            return object.toString();
        }
        return null;
    }

    /***
     * @param object
     * @return
     */
    public static int objectToInt(Object object) {
        if (object == null) return -1;
        try {
            if (object instanceof Double) {
                return ((Double) object).intValue();
            } else if (object instanceof String) {
                return Integer.valueOf(object.toString());
            } else if (object instanceof Integer) {
                return (Integer) object;
            } else if (object instanceof Float) {
                return ((Float) object).intValue();
            }
        } catch (ClassCastException e) {
            return -1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    /***
     * @param object
     * @return
     */
    public static Double objectToDouble(Object object) {
        if (object == null) return 0.0d;
        if (object instanceof Double) {
            return (Double) object;
        } else if (object instanceof String) {
            return Double.valueOf(object.toString());
        } else if (object instanceof Integer) {
            return ((Integer) object).doubleValue();
        } else if (object instanceof Float) {
            return ((Float) object).doubleValue();
        }
        return 0.0d;
    }

    /**
     * 获取时间戳
     *
     * @param date    系统时间
     * @param pattern 需要转换为时间戳的格式
     * @return 返回转换后的时间戳字符串
     */
    public static String getTimestamp(Date date, String pattern) {
        if (date == null) {
            return null;
        }
        SimpleDateFormat sdf = (SimpleDateFormat) SimpleDateFormat.getInstance();
        sdf.applyPattern(pattern);
        return sdf.format(date);
    }

    /***
     * 验证用户名的正确性 包含.的输入
     *
     * @param regNameEx
     * @return
     */
    public static boolean isRealName(String regNameEx) {
        if (TextUtils.isEmpty(regNameEx)) return false;
        if (regNameEx.contains("·")) {
            //包含特殊字符"·"
            Pattern p = Pattern.compile("^[\\u4e00-\\u9fa5]{1,10}(?:·[\\u4e00-\\u9fa5]{1,10})*$");
            Matcher m = p.matcher(regNameEx);
            return m.find();
        } else {
            //未包含特殊字符"·"，2~5个汉字
            Pattern p = Pattern.compile("^[\\u4e00-\\u9fa5]{2,10}$");
            Matcher m = p.matcher(regNameEx);
            return m.find();
        }
    }

    /**
     * 替换、过滤特殊字符
     */
    public static String StringFilter(String str) throws PatternSyntaxException {
        str = str.replaceAll("【", "[").replaceAll("】", "]").replaceAll("！", "!").replaceAll("，", ",").replaceAll("&", "\n");//替换中文标号
        String regEx = "[『』]"; // 清除掉特殊字符
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(str);
        return m.replaceAll("").trim();
    }

    /**
     * 格式化金额  以千分符  1000,000,00.00
     *
     * @param mMoney
     * @return
     */
    public static String formatMoneyWithSplite(Double mMoney) {
        BigDecimal loanAmount = new BigDecimal(mMoney);
        NumberFormat currency = NumberFormat.getNumberInstance();
        currency.setMaximumFractionDigits(2);
        currency.setMinimumFractionDigits(2);
        return currency.format(loanAmount);
    }
}
